package com.cosmoplat.gfqd.utils;

import com.cosmoplat.gfqd.config.BootStrapConfig;
import com.cosmoplat.gfqd.constants.Constants;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.InitCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
import org.gitlab4j.api.GitLabApi;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Group;
import org.gitlab4j.api.models.Project;
import org.gitlab4j.api.models.RepositoryFile;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class PushGitLab {
    private static String GITLAB_URL; // GitLab URL
    private static String ACCESS_TOKEN; // GitLab 访问令牌
    private static String GITLAB_ACCOUNT; // GitLab 账号
    private static String NEW_ARTIFACTID; // NewArtifactId
    private static Long PUSH_ORIGIN_GROUPID; // pushOriginGroupId
    private static String DEV = "dev"; //


    public static void push(BootStrapConfig config) {
        // 从配置文件加载 GitLab 配置
        if (config != null) {
            System.out.println("加载的 bootstrap 配置: " + config);
            // 获取配置信息
            GITLAB_URL = config.getGitlab().getUrl();
            ACCESS_TOKEN = config.getGitlab().getAccessToken();
            GITLAB_ACCOUNT = config.getGitlab().getAccount();
            NEW_ARTIFACTID = config.getGenerateProject().getNewArtifactId();
            PUSH_ORIGIN_GROUPID = config.getGenerateProject().getPushOriginGroupId();
        }

        if (PUSH_ORIGIN_GROUPID != null) {
            try {
                GitLabApi gitLabApi = new GitLabApi(GITLAB_URL, ACCESS_TOKEN);
                Group group = gitLabApi.getGroupApi().getGroup(PUSH_ORIGIN_GROUPID);

                if (Objects.nonNull(group)) {

                    //执行deploy，把各个项目的api打包
                    MavenExecutor.execute(new File(Constants.NEW_PROJECTS + "/" + NEW_ARTIFACTID), "mvn clean deploy");

                    // 推送项目到 GitLab
                    pushGitProject();

                    //更新项目描述
                    updateProjectDescriptionByGourpId(PUSH_ORIGIN_GROUPID);
                }

            } catch (GitLabApiException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static void pushGitProject() {
        List<ProjectStatus> projectStatuses = new ArrayList<>(); // 用于记录每个项目状态

        // GitLab 仓库 URL 模板（每个项目的远程仓库 URL）
        String remoteRepoUrlTemplate = GITLAB_URL + "/" + NEW_ARTIFACTID + "/server/%s.git";  // 使用 %s 占位符
        // 获取父目录下的所有子目录
        File parentDirectory = new File(Constants.NEW_PROJECTS + "/" + NEW_ARTIFACTID);
        if (parentDirectory.isDirectory()) {
            File[] subDirs = parentDirectory.listFiles(File::isDirectory);  // 获取所有子目录
            if (subDirs != null) {
                for (File subDir : subDirs) {
                    // 获取每个子目录的名称，作为项目名称
                    String projectName = subDir.getName();
                    // 生成 GitLab 仓库 URL
                    String remoteRepoUrl = String.format(remoteRepoUrlTemplate, projectName);
                    //push项目
                    boolean success = pushProjectProcess(subDir, remoteRepoUrl, projectName);
                    projectStatuses.add(new ProjectStatus(projectName, success));
                }

            } else {
                System.err.println("无法获取子目录列表！");
            }
        } else {
            System.err.println("给定的路径不是一个有效的目录！");
        }
        // 打印项目push结果
        printPushSummary(projectStatuses);

    }

    private static boolean pushProjectProcess(File subDir, String remoteRepoUrl, String projectName) {
        try {

            // Step 1: 初始化 Git 仓库
            File gitDir = new File(subDir, ".git");
            if (!gitDir.exists()) {
                InitCommand initCommand = Git.init();
                initCommand.setDirectory(subDir);
                initCommand.call();
            }
            Git git = Git.open(subDir);

            // Step 2: 添加所有更改到 Git 暂存区
            git.add().addFilepattern(".").call();

            // Step 3: 提交更改
            git.commit().setMessage("init").call();

            // Step 4: 添加远程仓库
            git.remoteAdd().setName("origin").setUri(new URIish(remoteRepoUrl)).call();

            // Step 5: 推送到远程仓库的 master 分支
            git.push()
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider(GITLAB_ACCOUNT, ACCESS_TOKEN)) // 使用用户名和密码（可根据实际情况选择 Token）
                    .setRemote("origin")
                    .call();

            // Step 6: 创建并切换到 dev 分支（如果不存在）
            if (!isBranchExists(git, DEV)) {
                git.checkout().setCreateBranch(true).setName(DEV).call();
            } else {
                git.checkout().setName(DEV).call();
            }

            // Step 7: 推送到远程仓库的 dev 分支
            git.push()
                    .setCredentialsProvider(new UsernamePasswordCredentialsProvider(GITLAB_ACCOUNT, ACCESS_TOKEN)) // 使用用户名和密码（可根据实际情况选择 Token）
                    .setRemote("origin")
                    .setRefSpecs(new RefSpec("refs/heads/" + DEV + ":refs/heads/" + DEV)) // 推送 dev 分支
                    .call();

            System.out.println("项目 " + projectName + " 成功推送到 GitLab!");

            return true;
        } catch (IOException | GitAPIException | URISyntaxException e) {
            System.err.println("推送项目 " + projectName + " 时发生错误: " + e.getMessage());
            return false;
        }
    }

    // 检查本地仓库是否存在指定分支
    private static boolean isBranchExists(Git git, String branchName) throws GitAPIException {
        return git.branchList().call().stream()
                .anyMatch(ref -> ref.getName().equals("refs/heads/" + branchName));
    }

    //更新项目描述
    private static boolean updateProjectDescriptionByGourpId(Long groupId) {

        try {
            GitLabApi gitLabApi = new GitLabApi(GITLAB_URL, ACCESS_TOKEN);
            List<ProjectStatus> projectStatuses = new ArrayList<>(); // 用于记录每个项目的克隆状态
            List<Project> projects = gitLabApi.getGroupApi().getProjects(groupId);
            // 批量执行克隆命令
            for (Project project : projects) {
                String projectName = project.getName();
                String projectGitUrl = project.getHttpUrlToRepo();

                System.out.println("update project: " + projectName + " from " + projectGitUrl);

                RepositoryFile readmeFile = gitLabApi.getRepositoryFileApi().getFile(project.getId(), "README.md",DEV);
                String readmeContent = new String(readmeFile.getDecodedContentAsBytes(), StandardCharsets.UTF_8);

                // 获取第一行内容
                String description = readmeContent.split("\n")[0];

                // 直接修改项目的描述字段
                project.setDescription(description); // 设置新的描述

                // 使用 ProjectApi 来更新项目
                gitLabApi.getProjectApi().updateProject(project);

                System.out.println("项目 " + project.getName() + " 的描述已更新为: " + description);

                projectStatuses.add(new ProjectStatus(projectName, true));
            }
            return true;
        } catch (GitLabApiException e) {
            System.err.println("Error accessing GitLab API: " + e.getMessage());
            return false;
        }
    }



    // 打印推送结果总结
    private static void printPushSummary(List<ProjectStatus> projectStatuses) {
        System.out.println("\n--- 推送总结 ---");
        int successCount = 0;
        for (ProjectStatus status : projectStatuses) {
            String result = status.isSuccess() ? "成功" : "失败";
            System.out.println("项目: " + status.getProjectName() + " - " + result);
            if (status.isSuccess()) {
                successCount++;
            }
        }
        System.out.println("总共项目数: " + projectStatuses.size());
        System.out.println("成功推送: " + successCount);
        System.out.println("推送失败: " + (projectStatuses.size() - successCount));
    }

}
